package Statistics;

import java.util.ArrayList;

import Definitions.GraphClass;
import Definitions.NodeClass;
import ShortestPath.DijkstraEngine;
import ShortestPath.MapHolder;

public class MetricsCalculatorClass {
	
	public class EccHolderClass
	{
		Double maximumEcc;
		Integer Xindx;
		Integer Yindx;
		Integer numberOfReachableNodes;
		Integer numberOfUnReachableNodes;
		
		EccHolderClass()
		{
			maximumEcc = 0.0; 
			Xindx = -1;
			Yindx = -1;		
			numberOfReachableNodes = 0;
			numberOfUnReachableNodes = 0;
		}
		
		void print()
		{
			System.out.println("maximumEcc:"+maximumEcc+" Xindx:"+Xindx+" Yindx:"+Yindx);			
			System.out.println("numberOfReachableNodes:"+numberOfReachableNodes+" numberOfUnReachableNodes:"+numberOfUnReachableNodes);
		}
	}
	
	EccHolderClass eccHolder[]; 
	
	public MetricsCalculatorClass(GraphClass graph, int edgeType)
	{
		MapHolder myRouteMap=new MapHolder(edgeType); 
  	  	DijkstraEngine engine = new DijkstraEngine(myRouteMap);
  	  	
  	  	NodeClass x=null, y=null;
		
		int sizeOfTheDataSet = graph.getDataSet().size();
		
		ArrayList <NodeClass> dataSet = graph.getDataSet();
		
		double currentDistance, totalDistanceOfAllPaths=0, maxDistance=0;
		int nodeXIndex=-1, nodeYIndex=-1;
		int numberOfPathsBetweenDistanceIsInfinite=0, totalNumberOfPathsFound=0;
		
		System.out.println("Zor ve uzun islem basliyor");
		
		eccHolder = new EccHolderClass[dataSet.size()];
		for(int k=0;k<eccHolder.length; k++)
			eccHolder[k]=new EccHolderClass();
			
  	  
  	  	for(int i=0; i<sizeOfTheDataSet; i++)
  	  	{
  	  		System.out.println("Now processing i:" + i + "/" + sizeOfTheDataSet);
  	  		
  	  		for(int j=i; j<sizeOfTheDataSet; j++)
  	  		{
  	  			x=dataSet.get(i);
  	  			y=dataSet.get(j);
  	  			engine.execute(x, y);
  	  			currentDistance=engine.getShortestDistance(y);
  	  			if(currentDistance!=DijkstraEngine.INFINITE_DISTANCE)
  	  			{
  	  				eccHolder[i].numberOfReachableNodes++;
  	  				eccHolder[j].numberOfReachableNodes++;
  	  				
  	  				totalNumberOfPathsFound++;
  	  				totalDistanceOfAllPaths += currentDistance;
  	  				if(currentDistance > maxDistance)
  	  				{
  	  					System.out.println("maxDistance:"+maxDistance+" currentDistance:"+currentDistance);
  	  					maxDistance = currentDistance;
  	  					nodeXIndex=i;
  	  					nodeYIndex=j;
  	  				}
  	  				
  	  				if(currentDistance>eccHolder[i].maximumEcc)
  	  				{
  	  					eccHolder[i].maximumEcc=currentDistance;
  	  					eccHolder[i].Xindx = i;
  	  					eccHolder[i].Yindx = j;
  	  					
  	  					if(currentDistance>eccHolder[j].maximumEcc)
  	  					{
  	  						eccHolder[j].maximumEcc=currentDistance;
  	  						eccHolder[j].Xindx = j;
  	  						eccHolder[j].Yindx = i;
  	  					}	  				
  	  				}
  	  			}
  	  			else
  	  			{
  	  				numberOfPathsBetweenDistanceIsInfinite++;
  	  				eccHolder[i].numberOfUnReachableNodes++;
  	  				eccHolder[j].numberOfUnReachableNodes++;
  	  			}
  	  				
  	  		}
  	  	}
  	  
  	  	System.out.println("maxDistance:"+maxDistance);
  	  	System.out.println("nodeXIndex:"+nodeXIndex);
  	  	System.out.println("Order of X:"+dataSet.get(nodeXIndex).getOrder());
  	  	System.out.println("ID of X:"+dataSet.get(nodeXIndex).getId());
  	  	System.out.println("nodeYIndex:"+nodeYIndex);
  	  	System.out.println("Order of Y:"+dataSet.get(nodeYIndex).getOrder());
	  	System.out.println("ID of Y:"+dataSet.get(nodeYIndex).getId());  	  	
  	  	System.out.println("totalNumberOfPathsFound:"+totalNumberOfPathsFound);
  	  	System.out.println("numberOfPathsBetweenDistanceIsInfinite:"+numberOfPathsBetweenDistanceIsInfinite);  	  
  	  	System.out.println("totalDistanceOfAllPaths:"+totalDistanceOfAllPaths);
  	  	System.out.println("Ort distance:"+(2*totalDistanceOfAllPaths)/(sizeOfTheDataSet*(sizeOfTheDataSet-1))); 	  	
  	  	System.out.println("Ort distance deneme:"+(double)(totalDistanceOfAllPaths)/(totalNumberOfPathsFound));
  	  	
  	  	/*
  	  	System.out.println("Now printing ecc:");
  	  	
  	  	for(int k=0; k <eccHolder.length; k++)
  	  	{
  	  		eccHolder[k].print(); 	  		
  	  	}*/
  	  	
  	  	Double minOfMaxEcc=Double.MAX_VALUE;
  	  	Integer indexOfRadiusNode=-1;
  	  	
  	  	
  	  	
  	  	
  	  	for(int k=0; k <eccHolder.length; k++)
  	  	{
  	  		if(eccHolder[k].maximumEcc!= 0 && eccHolder[k].maximumEcc < minOfMaxEcc)
  	  		{
  	  			minOfMaxEcc = eccHolder[k].maximumEcc;
  	  			indexOfRadiusNode = k;  	  			
  	  		}  	  		
  	  	}
  	  	
  	  System.out.println("minOfMaxEcc:"+minOfMaxEcc);
  	  System.out.println("indexOfRadiusNode:"+indexOfRadiusNode);
	  System.out.println("Order of RadiusNode:"+dataSet.get(indexOfRadiusNode).getOrder());
  	  System.out.println("ID of RadiusNode:"+dataSet.get(indexOfRadiusNode).getId());
  	  
  	  System.out.println("minOfMaxEcc:"+eccHolder[indexOfRadiusNode].maximumEcc+"X:" +eccHolder[indexOfRadiusNode].Xindx+" Y:"+eccHolder[indexOfRadiusNode].Yindx);
  	  
  	  
  	  }
}
